#include "QBSortVContainer.h"

#include <sstream>

#include "BondCDCPriceInfo.h"
#include "BondCSIPriceInfo.h"
#include "BondContainer.h"
#include "BondInfo.h"
#include "SSCFETSQuote.h"
#include "qbprotocol/include/SSQBAModel.h"

#define SP_ASSERT  //
namespace {
inline bool IsEmpty(const char* str) {
  // 旧代码是 strlen(str)<=0;
  return str == nullptr || *str == '\0';
}
inline bool CheckPriceZero(double price) {
  // 之前代码中,不检查价格<=PRECISION5,会导致JIRA 10761 的问题
  return price <= PRECISION5 && price >= -PRECISION5;
}
}  // namespace
const char* GetBidEstPrice(const REPORT& report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid,
                           bool bExchange) {
  SP_ASSERT(pBond != NULL);
  if (strcmp(report.m_bidinfo.m_price_status, "0") == 0) {
    return "--";
  }

  double dBidPrice = atof(report.m_bidinfo.m_yield_price);
  int qt = atoi(report.m_bidinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dBidPrice <= 0.0 || dBidPrice >= 30.0) {
      return "--";
    }
  }

  int exec = -1;
  if (bExchange)
    exec = 1;
  else if (pBond->IsRight() && report.m_bidinfo.m_exercise[0] != 0)
    exec = atoi(report.m_bidinfo.m_exercise);

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, true,
      report.m_bidinfo.m_yield_price, INVALID_CDC_VALUE, exec);
  if (dValue <= INVALID_CDC_VALUE) return "--";

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}
const char* GetBidEstPrice(const REPORT& report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);
  if (strcmp(report.m_bidinfo.m_price_status, "0") == 0) {
    return "--";
  }

  double dBidPrice = atof(report.m_bidinfo.m_yield_price);
  int qt = atoi(report.m_bidinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dBidPrice <= 0.0 || dBidPrice >= 30.0) {
      return "--";
    }
  }

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, true,
      report.m_bidinfo.m_yield_price, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}

std::string GetBidEstPrice(const char* pBidPrice, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);

  double dBidPrice = atof(pBidPrice);
  if (dBidPrice >= 30) {
    return "--";
  }

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, true,
      pBidPrice, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";

  char sValue[30] = {0};
  FMTBUF(sValue, "%.2f", dValue);
  return std::string(sValue);
}

const char* GetEstPriceOfr(const REPORT& report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid,
                           bool bExchange) {
  SP_ASSERT(pBond != NULL);

  if (strcmp(report.m_askinfo.m_price_status, "0") == 0) {
    return "--";
  }

  double dOfrPrice = atof(report.m_askinfo.m_yield_price);
  int qt = atoi(report.m_askinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) {
      return "--";
    }
  }

  int exec = -1;
  if (bExchange)
    exec = 1;
  else if (pBond->IsRight() && report.m_askinfo.m_exercise[0] != 0)
    exec = atoi(report.m_askinfo.m_exercise);

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false,
      report.m_askinfo.m_yield_price, INVALID_CDC_VALUE, exec);
  if (dValue <= INVALID_CDC_VALUE) return "--";
  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}

const char* GetBidEstPrice(int nBondIndex, const std::string& sBrokerID,
                           bool bIsCDCAuthValid) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepById(nBondIndex,
                                                   sBrokerID.c_str(), report)) {
    return GetBidEstPrice(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex),
                          nBondIndex, bIsCDCAuthValid);
  }

  return "--";
}

const char* GetBidEstPriceBySettlement(int nBondIndex,
                                       const std::string& sBrokerID,
                                       bool bIsCDCAuthValid,
                                       BYTE btSettlement) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepByIdAndSettlement(
          nBondIndex, sBrokerID.c_str(), btSettlement, report)) {
    return GetBidEstPrice(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex),
                          nBondIndex, bIsCDCAuthValid);
  }

  return "--";
}

const char* GetBidEstPriceMixedBP(const BrokerKey& key, bool bIsCDCAuthValid,
                                  BYTE btPriceFilter) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  int bondIndex = key.m_nIndex;
  const char* contributorId = key.GetBrokerId().c_str();
  if (CBondContainer::instance().GetBrokerMixedBPRepByIdAndPriceFilter(
          bondIndex, contributorId, btPriceFilter, report)) {
    return GetBidEstPrice(report,
                          &CBondContainer::instance().ElementAtR(bondIndex),
                          bondIndex, bIsCDCAuthValid, false);
  }

  return "--";
}

const char* GetBidEstPrice(const CFETSQUOTE* report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);
  SP_ASSERT(report != nullptr);

  if (strcmp(report->m_BidPriceYield, "0") == 0 ||
      strcmp(report->m_BidPriceYield, "bid") == 0 ||
      strcmp(report->m_BidPriceYield, "Bid") == 0 ||
      IsEmpty(report->m_BidPriceYield))
    return "--";

  double dBidPrice = atof(report->m_BidPriceYield);

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, true,
      report->m_BidPriceYield, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}

const char* GetEstPriceOfr(const REPORT& report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);

  if (strcmp(report.m_askinfo.m_price_status, "0") == 0) {
    return "--";
  }

  double dOfrPrice = atof(report.m_askinfo.m_yield_price);
  int qt = atoi(report.m_askinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) {
      return "--";
    }
  }

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false,
      report.m_askinfo.m_yield_price, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";
  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}

std::string GetEstPriceOfr(const char* pOfrPrice, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);
  SP_ASSERT(pOfrPrice != nullptr);

  double dOfrPrice = atof(pOfrPrice);
  if (dOfrPrice >= 30) {
    return "--";
  }

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false,
      pOfrPrice, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";

  char sValue[30] = {0};
  FMTBUF(sValue, "%.2f", dValue);
  return std::string(sValue);
}

const char* GetEstPriceOfr(int nBondIndex, const std::string& sBrokerID,
                           bool bIsCDCAuthValid) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepById(nBondIndex,
                                                   sBrokerID.c_str(), report)) {
    return GetEstPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex),
                          nBondIndex, bIsCDCAuthValid);
  }

  return "--";
}

const char* GetEstPriceOfrBySettlement(int nBondIndex,
                                       const std::string& sBrokerID,
                                       bool bIsCDCAuthValid,
                                       BYTE btSettlement) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepByIdAndSettlement(
          nBondIndex, sBrokerID.c_str(), btSettlement, report)) {
    return GetEstPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex),
                          nBondIndex, bIsCDCAuthValid);
  }

  return "--";
}

const char* GetEstPriceOfrMixedBP(const BrokerKey& key, bool bIsCDCAuthValid,
                                  BYTE btPriceFilter) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  int bondIndex = key.m_nIndex;
  const char* contributorId = key.GetBrokerId().c_str();
  if (CBondContainer::instance().GetBrokerMixedBPRepByIdAndPriceFilter(
          bondIndex, contributorId, btPriceFilter, report)) {
    return GetEstPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(bondIndex),
                          bondIndex, bIsCDCAuthValid, false);
  }

  return "--";
}

const char* GetEstPriceOfr(const CFETSQUOTE* report, const CBondInfo* pBond,
                           const int nBondIndex, bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);
  SP_ASSERT(report != nullptr);

  if (strcmp(report->m_OfrPriceYield, "0") == 0 ||
      strcmp(report->m_OfrPriceYield, "bid") == 0 ||
      strcmp(report->m_OfrPriceYield, "Bid") == 0 ||
      IsEmpty(report->m_OfrPriceYield))
    return "--";
  double dOfrPrice = atof(report->m_OfrPriceYield);

  double dValue = CBondCDCPriceInfo::instance().GetYesterdayCDCPriceGap(
      bIsCDCAuthValid, nBondIndex, CBondCDCPriceInfo::price_type_yield, false,
      report->m_OfrPriceYield, INVALID_CDC_VALUE, false);
  if (dValue <= INVALID_CDC_VALUE) return "--";
  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.2f", dValue);
  return sValue;
}

const char* GetBidCsiPrice(const REPORT& report, const CBondInfo* pBond) {
  SP_ASSERT(pBond != nullptr);

  if (/*IsEmpty(pBond->GetCSYield()) || */ strcmp(
          report.m_bidinfo.m_price_status, "0") == 0 ||
      IsEmpty(report.m_bidinfo.m_yield_price)) {
    return "--";
  }

  double dBidPrice = atof(report.m_bidinfo.m_yield_price);
  int qt = atoi(report.m_bidinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dBidPrice <= 0.0 || dBidPrice >= 30.0) {
      return "--";
    }
  }

  // double dValue = (dBidPrice - atof(pBond->GetCSYield())) * 100;
  // static char sValue[30] = "--";//{0};
  // memset(sValue,0,sizeof(sValue));
  // FMTBUF(sValue, "%.2f", dValue);
  // return sValue;

  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveExercise() && !xUnit.IsHaveMarturity()) return "--";

  double dExercise =
      xUnit.IsHaveExercise() ? xUnit.m_dYieldToExercise : _INVALID_CSI_VALUE;
  double dMaturity =
      xUnit.IsHaveMarturity() ? xUnit.m_dYieldToMaturity : _INVALID_CSI_VALUE;

  // double dBidPrice = atof(report.m_bidinfo.m_yield_price);

  static char sValue[30] = "--";

  double dRet = _INVALID_CSI_VALUE;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dBidPrice - dExercise;
    dMaturity = dBidPrice - dMaturity;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dExercise;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dMaturity;
  }

  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", dRet * 100);

  return sValue;
}

const char* GetBidCsiPrice(int nBondIndex, const std::string& sBrokerID) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepById(nBondIndex,
                                                   sBrokerID.c_str(), report)) {
    return GetBidCsiPrice(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex));
  }

  return "--";
}

const char* GetBidCsiPriceBySettlement(int nBondIndex,
                                       const std::string& sBrokerID,
                                       BYTE btSettlement) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepByIdAndSettlement(
          nBondIndex, sBrokerID.c_str(), btSettlement, report)) {
    return GetBidCsiPrice(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex));
  }
  return "--";
}

const char* GetBidCsiPriceMixedBP(const BrokerKey& key, BYTE btPriceFilter) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  int bondIndex = key.m_nIndex;
  const char* contributorId = key.GetBrokerId().c_str();
  if (CBondContainer::instance().GetBrokerMixedBPRepByIdAndPriceFilter(
          bondIndex, contributorId, btPriceFilter, report)) {
    return GetBidCsiPrice(report,
                          &CBondContainer::instance().ElementAtR(bondIndex));
  }
  return "--";
}

const char* GetBidCsiPrice(const CFETSQUOTE* report, const CBondInfo* pBond) {
  SP_ASSERT(pBond != nullptr);
  SP_ASSERT(report != nullptr);
  if (/*IsEmpty(pBond->GetCSYield()) || */ strcmp(report->m_BidPriceYield,
                                                  "0") == 0 ||
      strcmp(report->m_BidPriceYield, "bid") == 0 ||
      strcmp(report->m_BidPriceYield, "Bid") == 0 ||
      IsEmpty(report->m_BidPriceYield)) {
    return "--";
  }

  double dBidPrice = atof(report->m_BidPriceYield);
  if (dBidPrice <= 0.0 || dBidPrice >= 30.0) return "--";

  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveExercise() && !xUnit.IsHaveMarturity()) return "--";

  double dExercise =
      xUnit.IsHaveExercise() ? xUnit.m_dYieldToExercise : _INVALID_CSI_VALUE;
  double dMaturity =
      xUnit.IsHaveMarturity() ? xUnit.m_dYieldToMaturity : _INVALID_CSI_VALUE;

  static char sValue[30] = "--";

  double dRet = _INVALID_CSI_VALUE;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dBidPrice - dExercise;
    dMaturity = dBidPrice - dMaturity;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dExercise;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dBidPrice - dMaturity;
  }

  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", dRet * 100.0000);

  return sValue;
}

const char* GetCsiPriceOfr(const REPORT& report, const CBondInfo* pBond) {
  SP_ASSERT(pBond != nullptr);

  if (/*IsEmpty(pBond->GetCSYield()) || */ strcmp(
          report.m_askinfo.m_price_status, "0") == 0 ||
      IsEmpty(report.m_askinfo.m_yield_price)) {
    return "--";
  }

  double dOfrPrice = atof(report.m_askinfo.m_yield_price);
  int qt = atoi(report.m_askinfo.m_quotetype);
  if (qt != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) {
      return "--";
    }
  }

  // double dValue = (atof(pBond->GetCSYield()) - dOfrPrice) * 100;
  static char sValue[30] = {0};
  // memset(sValue,0,sizeof(sValue));
  // FMTBUF(sValue, "%.2f", dValue);
  // return sValue;

  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveExercise() && !xUnit.IsHaveMarturity()) return "--";

  double dExercise =
      xUnit.IsHaveExercise() ? xUnit.m_dYieldToExercise : _INVALID_CSI_VALUE;
  double dMaturity =
      xUnit.IsHaveMarturity() ? xUnit.m_dYieldToMaturity : _INVALID_CSI_VALUE;

  // double dOfrPrice = atof(report.m_askinfo.m_yield_price);

  int nQuoteType = atoi(report.m_askinfo.m_quotetype);
  if (nQuoteType != 3 &&
      (pBond->IsBondABS() ||
       pBond->IsTransBond()))  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) return "--";
  }

  double dRet = _INVALID_CSI_VALUE;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dExercise - dOfrPrice;
    dMaturity = dMaturity - dOfrPrice;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dExercise - dOfrPrice;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dMaturity - dOfrPrice;
  }

  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", dRet * 100.0000);

  return sValue;
}

const char* GetCsiPriceOfr(int nBondIndex, const std::string& sBrokerID) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepById(nBondIndex,
                                                   sBrokerID.c_str(), report)) {
    return GetCsiPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex));
  }

  return "--";
}

const char* GetCsiPriceOfrBySettlement(int nBondIndex,
                                       const std::string& sBrokerID,
                                       BYTE btSettlement) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  if (CBondContainer::instance().GetCompanyRepByIdAndSettlement(
          nBondIndex, sBrokerID.c_str(), btSettlement, report)) {
    return GetCsiPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(nBondIndex));
  }

  return "--";
}

const char* GetCsiPriceOfrMixedBP(const BrokerKey& key, BYTE btPriceFilter) {
  REPORT report;
  memset(&report, 0, sizeof(REPORT));
  int bondIndex = key.m_nIndex;
  const char* contributorId = key.GetBrokerId().c_str();
  if (CBondContainer::instance().GetBrokerMixedBPRepByIdAndPriceFilter(
          bondIndex, contributorId, btPriceFilter, report)) {
    return GetCsiPriceOfr(report,
                          &CBondContainer::instance().ElementAtR(bondIndex));
  }
  return "--";
}

const char* GetCsiPriceOfr(const CFETSQUOTE* report, const CBondInfo* pBond) {
  SP_ASSERT(pBond != nullptr);
  SP_ASSERT(report != nullptr);

  if (strcmp(report->m_OfrPriceYield, "0") == 0 ||
      strcmp(report->m_OfrPriceYield, "ofr") == 0 ||
      strcmp(report->m_OfrPriceYield, "Ofr") == 0 ||
      IsEmpty(report->m_OfrPriceYield)) {
    return "--";
  }

  double dOfrPrice = atof(report->m_OfrPriceYield);
  if (pBond->IsBondABS() ||
      pBond->IsTransBond())  // quotetype不是收益率，仅ABS和可转债判定0-30
  {
    if (dOfrPrice <= 0.0 || dOfrPrice >= 30.0) return "--";
  }

  static char sValue[30] = {0};
  xCSIUint_c xUnit;
  if (!CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xUnit))
    return "--";

  if (!xUnit.IsHaveExercise() && !xUnit.IsHaveMarturity()) return "--";

  double dExercise =
      xUnit.IsHaveExercise() ? xUnit.m_dYieldToExercise : _INVALID_CSI_VALUE;
  double dMaturity =
      xUnit.IsHaveMarturity() ? xUnit.m_dYieldToMaturity : _INVALID_CSI_VALUE;

  double dRet = _INVALID_CSI_VALUE;
  if (dExercise > _INVALID_CSI_VALUE && dMaturity > _INVALID_CSI_VALUE) {
    dExercise = dExercise - dOfrPrice;
    dMaturity = dMaturity - dOfrPrice;
    dRet = abs(dExercise) < abs(dMaturity) ? dExercise : dMaturity;
  } else if (dExercise > _INVALID_CSI_VALUE) {
    dRet = dExercise - dOfrPrice;
  } else if (dMaturity > _INVALID_CSI_VALUE) {
    dRet = dMaturity - dOfrPrice;
  }

  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", dRet * 100.0000);
  return sValue;
}

const char* GetCsi_CdcPrice(const CBondInfo* pBond, const int nBondIndex,
                            bool bIsCDCAuthValid) {
  SP_ASSERT(pBond != nullptr);

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));

  double dCdcExercise = INVALID_CDC_VALUE;
  double dCdcMaturity = INVALID_CDC_VALUE;
  CBondCDCPriceInfo::instance().GetExerciseAndMaturity(
      bIsCDCAuthValid, nBondIndex, dCdcExercise, dCdcMaturity);

  double dCsiExercise = _INVALID_CSI_VALUE;
  double dCsiMaturity = _INVALID_CSI_VALUE;
  xCSIUint_c xcsi;
  if (CBondCSInfo::instance().GetCsiUnit(pBond->GetCombBondKey(), xcsi)) {
    dCsiExercise = xcsi.m_dYieldToExercise;
    dCsiMaturity = xcsi.m_dYieldToMaturity;
  } else {
    return "--";
  }

  bool bExerciseValid = false;
  char szExercise[32] = {0};
  if (dCdcExercise <= INVALID_CDC_VALUE || dCsiExercise <= _INVALID_CSI_VALUE) {
    FMTBUF(szExercise, "%s", "--");
  } else {
    bExerciseValid = true;
    FMTBUF(szExercise, "%.4f", dCsiExercise - dCdcExercise);
  }

  bool bMaturityValid = false;
  std::string sExercise;
  char szMaturity[32] = {0};
  if (dCdcMaturity <= INVALID_CDC_VALUE || dCsiMaturity <= _INVALID_CSI_VALUE) {
    FMTBUF(szMaturity, "%s", "--");
  } else {
    bMaturityValid = true;
    FMTBUF(szMaturity, "%.4f", dCsiMaturity - dCdcMaturity);
  }

  if (bExerciseValid && bMaturityValid) {
    FMTBUF(sValue, "%.4f", dCsiExercise - dCdcExercise);
  } else if (bExerciseValid) {
    FMTBUF(sValue, "%s", szExercise);
  } else if (bMaturityValid) {
    FMTBUF(sValue, "%s", szMaturity);
  } else {
    FMTBUF(sValue, "%s", "--");
  }

  return sValue;
}

const char* GetCsi_CdcPrice(int nBondIndex, bool bIsCDCAuthValid) {
  if (CBondContainer::instance().IsValidIndex(nBondIndex)) {
    return GetCsi_CdcPrice(&CBondContainer::instance().ElementAtR(nBondIndex),
                           nBondIndex, bIsCDCAuthValid);
  }

  return "--";
}

const char* GetCleanPriceDiv(const char* lpszTknCleanPrice,
                             const char* lpszCdcCleanPrice) {
  if (lpszCdcCleanPrice == nullptr || lpszCdcCleanPrice == nullptr) {
    return "--";
  }

  if (IsEmpty(lpszTknCleanPrice) || IsEmpty(lpszCdcCleanPrice)) {
    return "--";
  }

  float fCleanPrice = atof(lpszTknCleanPrice);
  float fCdcCleanPrice = atof(lpszCdcCleanPrice);
  if (fabs(fCdcCleanPrice) <= 0.000001) {
    return "--";
  }

  float fValue = (fCleanPrice / fCdcCleanPrice - 1) * 100;

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", fValue);

  return sValue;
}

const char* GetYieldDiv(const char* lpszCdcVal, const char* lpszTknYield) {
  if (lpszCdcVal == nullptr || lpszTknYield == nullptr) {
    return "--";
  }

  if (IsEmpty(lpszCdcVal) || IsEmpty(lpszTknYield)) {
    return "--";
  }

  float fValue = atof(lpszCdcVal) - atof(lpszTknYield);

  static char sValue[30] = {0};
  memset(sValue, 0, sizeof(sValue));
  FMTBUF(sValue, "%.4f", fValue);
  return sValue;
}

bool GetMarketStreamInfo(const CBondInfo* pBond, const char* lpszBrokerID,
                         std::vector<MarketStreamInfo>* pStream,
                         MarketStreamInfo& streamInfo) {
  if (pBond == nullptr || lpszBrokerID == nullptr || pStream == nullptr) {
    return false;
  }

  std::vector<MarketStreamInfo>::iterator itor = pStream->begin();
  for (; itor != pStream->end(); ++itor) {
    if (strcmp(pBond->GetBondKey(), itor->m_body.m_bondkey) == 0 &&
        strcmp(pBond->GetListedMarket(), itor->m_body.m_listedmarket) == 0 &&
        strcmp(lpszBrokerID, itor->m_company_id) == 0) {
      streamInfo = *itor;
      return true;
    }
  }

  return false;
}

bool IsEqual(double dVal1, double dVal2) {
  if (fabs(dVal1 - dVal2) <= PRECISION6) {
    return true;
  }

  return false;
}

bool IsLess(double dVal1, double dVal2) {
  if (fabs(dVal1 - dVal2) <= PRECISION6) {
    return false;
  }

  return dVal1 < dVal2;
}

bool IsLessAndEqual(double dVal1, double dVal2) {
  if (fabs(dVal1 - dVal2) <= PRECISION6) {
    return true;
  }

  return dVal1 < dVal2;
}

bool IsGreater(double dVal1, double dVal2) {
  if (fabs(dVal1 - dVal2) <= PRECISION6) {
    return false;
  }

  return dVal1 > dVal2;
}

bool IsGreaterAndEqual(double dVal1, double dVal2) {
  if (fabs(dVal1 - dVal2) <= PRECISION6) {
    return true;
  }

  return dVal1 > dVal2;
}